#include "OsipProcess.h"
#include "app.h"
#include "string.h"
#include "errno.h"

//Keep this for the old version.
SOCKET UdpSocked;

int ExSockStartPort=20000;
SOCKET ExtUdpSocks[MAX_EX_SOCK_NUM];

static wxMutex s_mutexProtectingSocked;
extern bool bindflag;

static wxMutex s_mutexProtectingGlobalStitMap;
StrLongHash GlobalRcvMsgStatistic,GlobalSntMsgStatistic;

int GetSipMsgName(osip_message_t *osip,char *sName)
{
    if(NULL == sName)
        return -1;

    if(NULL == osip)
        return -1;

    if(MSG_IS_RESPONSE(osip))
        sprintf(sName,"%d(%s)",osip->status_code,osip->cseq->method);
    else
        strcpy(sName,osip->sip_method);

    return 0;
}

void ClearGlobalStat(){
  wxMutexLocker lock(s_mutexProtectingGlobalStitMap);
  GlobalRcvMsgStatistic.clear();
  GlobalSntMsgStatistic.clear();
}

void DoGlobalMsgStatReport(std::string &buf){
  wxMutexLocker lock(s_mutexProtectingGlobalStitMap);
  buf+=Scenario::Conv2Std(_("<h2>Global Msg Statistic(with retransmit message)</h2>"));;
  buf+=Scenario::Conv2Std(_("<h3>Receive Msg Statistic</h3>"));
  buf+="<table cellpadding=\"7\" cellspacing=\"1\" border=\"1\" width=\"100%\">";
  for (StrLongHash::iterator iter=GlobalRcvMsgStatistic.begin(); iter!=GlobalRcvMsgStatistic.end();iter++){
    buf+="<tr>";
    buf+=Scenario::Conv2Std(wxString::Format(wxT("<td>%s</td><td>%ld</td>"),iter->first.c_str(),iter->second));
    buf+="</tr>";
  }
  buf+="</table>";

  buf+=Scenario::Conv2Std(_("<h3>Sent Msg Statistic</h3>"));;
  buf+="<table cellpadding=\"7\" cellspacing=\"1\" border=\"1\" width=\"100%\">";
  {
	  for (StrLongHash::iterator iter=GlobalSntMsgStatistic.begin(); iter!=GlobalSntMsgStatistic.end();iter++){
		buf+="<tr>";
		buf+=Scenario::Conv2Std(wxString::Format(wxT("<td>%s</td><td>%ld</td>"),iter->first.c_str(),iter->second));
		buf+="</tr>";
	  }
  }
  buf+="</table>";
}

void DoRecvMsgStatistic(osip_message_t *sip, char*msg, int n, wxString desc){
  wxMutexLocker lock(s_mutexProtectingGlobalStitMap);
  wxString Key;
  if (sip){
    if (MSG_IS_REQUEST(sip)){
      if (MSG_IS_REGISTER(sip)){
	osip_header_t *head=NULL;
	osip_message_get_expires(sip,0,&head);
	if ((head) &&(head->hvalue)){
	  int e=atoi(head->hvalue);
	if (e>0){
	  Key=wxT("Register");
	}
	else{
	  Key=wxT("DeRegister");
	}
	}
	else{
	  Key=wxT("BadRegister");
	}
      }
      else if (MSG_IS_SUBSCRIBE(sip)){
	osip_header_t *head;
	osip_message_get_expires(sip,0,&head);
	if ((head) &&(head->hvalue)){
	  int e=atoi(head->hvalue);
	  if (e>0){
	    Key=wxT("Subscribe");
	  }
	  else{
	    Key=wxT("DeSubscribe");
	  }
	}
	else{
	  Key=wxT("BadSubscribe");
	}
      }
      else{
	Key=STT_LStr(sip->sip_method);
      }
    }
    else {
      Key=STT_LStr(sip->cseq->method);
      Key+=wxString::Format(wxT(" Rsp(%d)"),sip->status_code);
    }
  }
  Key=desc+Key;

  if (GlobalRcvMsgStatistic.find(Key) == GlobalRcvMsgStatistic.end()){
    GlobalRcvMsgStatistic[Key]=1;
  }
  else{
    GlobalRcvMsgStatistic[Key]++;
  }
}

void DoSendMsgStatistic(osip_message_t *sip, char*msgP,int msgLen){
  wxMutexLocker lock(s_mutexProtectingGlobalStitMap);
  if (!sip) return;
  wxString Key;
  if (MSG_IS_REQUEST(sip)){
    if (MSG_IS_REGISTER(sip)){
      osip_header_t *head=NULL;
      osip_message_get_expires(sip,0,&head);
      if ((head) &&(head->hvalue)){
	int e=atoi(head->hvalue);
	if (e>0){
	  Key=wxT("Register");
	}
	else{
	  Key=wxT("DeRegister");
	}
      }
      else{
	Key=wxT("BadRegister");
      }
    }
    else if (MSG_IS_SUBSCRIBE(sip)){
      osip_header_t *head;
      osip_message_get_expires(sip,0,&head);
      if ((head) &&(head->hvalue)){
	int e=atoi(head->hvalue);
	if (e>0){
	  Key=wxT("Subscribe");
	}
	else{
	  Key=wxT("DeSubscribe");
	}
      }
      else{
	Key=wxT("BadSubscribe");
      }
    }
    else{
      Key=STT_LStr(sip->sip_method);
    }
  }
  else {
    Key=STT_LStr(sip->cseq->method);
    Key+=wxString::Format(wxT(" Rsp(%d)"),sip->status_code);
  }

  if (GlobalSntMsgStatistic.find(Key) == GlobalSntMsgStatistic.end()){
    GlobalSntMsgStatistic[Key]=1;
  }
  else{
    GlobalSntMsgStatistic[Key]++;
  }
}

void CloseAllSocket(void){
    shutdown(UdpSocked,2);
    for (int i=0;i<MAX_EX_SOCK_NUM;i++){
	shutdown(ExtUdpSocks[i],2);
    }
}

bool InitOsipSendSock(void){
	UdpSocked = socket(AF_INET,SOCK_DGRAM,0);
	int n=1;
	setsockopt(UdpSocked,SOL_SOCKET,SO_REUSEADDR,(const char*)&n,sizeof(int));
	struct sockaddr_in servaddr;
	memset(&servaddr, 0, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = INADDR_ANY;
	servaddr.sin_port = htons(5060);
	if (bindflag){
		if(bind(UdpSocked, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
		{
			STT_TRACE(-1,TL_ERROR,_("Bind Socked Return Error!!"));
			return false;
		}
	}

	for (int i=0;i<MAX_EX_SOCK_NUM;i++){
	    if ((i % 10)==0){
		wxGetApp().StepSplash(_("Create Extend socket..."));
	    }
	    ExtUdpSocks[i]=socket(AF_INET,SOCK_DGRAM,0);
	    setsockopt(ExtUdpSocks[i],SOL_SOCKET,SO_REUSEADDR,(const char*)&n,sizeof(int));
	    memset(&servaddr, 0, sizeof(servaddr));
	    servaddr.sin_family = AF_INET;
	    servaddr.sin_addr.s_addr = INADDR_ANY;
	    servaddr.sin_port = htons(ExSockStartPort+i);
	    if (bindflag){
		if(bind(ExtUdpSocks[i], (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
		    STT_TRACE(-1,TL_ERROR,wxString::Format(_("Bind ExSocked %d Return Error!!"),i));
		    return false;
		}
	    }
	}

	return true;
}


int
myosip_message_header_get_byname (const osip_message_t * sip, const char *hname,
                                int pos, osip_header_t ** dest)
{
  int i;
  osip_header_t *tmp;

  *dest = NULL;
  i = pos;
  if (osip_list_size (sip->headers) <= pos)
    return -1;                  /* NULL */
  while (osip_list_size (sip->headers) > i)
    {
      tmp = (osip_header_t *) osip_list_get (sip->headers, i);
      if (osip_strcasecmp (tmp->hname, hname) == 0)
        {
          *dest = tmp;
          return i;
        }
      i++;
    }
  return -1;                    /* not found */
}

int ForcePort=0;
int SendOsipMsg(osip_transaction_t *tr,osip_message_t *sip, char *host,int port, int out_socket)
{
	char *msgP;
	size_t msgLen;
	int i;
	int Uid=-1;
	TermControl *TermIns=NULL;
	if (wxGetApp().AllTranses.IsAlive(tr)){
	  TermIns = (TermControl *)osip_transaction_get_your_instance(tr);
	}

	//Some Message need custom route head,so we need foce the dest.
	osip_header_t *dest;
	if (myosip_message_header_get_byname(sip,"ForceDestHost",0,&dest)>=0){
	  host = dest->hvalue;
	}
	if (myosip_message_header_get_byname(sip,"ForceDestPort",0,&dest)>=0){
	  port = atoi(dest->hvalue);
	}


	if ((TermIns) && (MSG_IS_ACK(sip))){
	  if (!TermIns->pCallInfo->pCurSce->AllowAutoAck){
		if (myosip_message_header_get_byname(sip,"UserAck",0,&dest)<0){
		  STT_TRACE(TermIns->Uid,TL_MESSAGE, _("in this case,Auto Ack is not allowed, Try to add a UserAck head with any value\n"));
		  return 0;
		}
	  }
	}
	/*
	//Fix the bug of lose max-forward in auto ack message;
        if (MSG_IS_ACK(sip)){
           const char* UaTag="Max-Forwards";
	   osip_header_t *dest;
	   if (osip_message_header_get_byname(sip,UaTag,0,&dest)<0){
		osip_message_set_header(sip,UaTag,"70");
	   }
        }
	*/
		
	if((i = osip_message_to_str(sip, &msgP, &msgLen)) != 0){
		STT_TRACE(-1,TL_ERROR, _("failed to convert message\n"));
		return -1;
	}

	msgLen+=1;
	struct sockaddr_in address;
	struct hostent* hostp;
	if (( hostp = gethostbyname(host)) == NULL) {
	    STT_TRACE(-1, TL_ERROR,wxString::Format(_("gethostbyname failed, h_errno = %d: %s\n"), h_errno,	STT_LStr(host)));
	    printf("gethostbyname failed, h_errno = %d: %s\n",h_errno,host);
	    STT_TRACE(-1,TL_ERROR,wxString::Format(wxString(wxT("[%s %d]"))+_("[Total Len:%d]:\n%s"),STT_LStr(host), port, msgLen, STT_LStr(msgP)));
	    osip_free(msgP);
	    if (MSG_IS_RESPONSE(sip) && tr && tr->orig_request){
            if((i = osip_message_to_str(tr->orig_request, &msgP, &msgLen)) == 0){
                STT_TRACE(-1,TL_ERROR,wxString::Format(wxString(wxT("[%s %d]"))+_("Orig Request:[Total Len:%d]:\n%s"),STT_LStr(host), port, msgLen, STT_LStr(msgP)));
            }
            else{
                STT_TRACE(-1,TL_ERROR,_("Convert the origin request fail!"));
            }
	    }
	    if (wxGetApp().AllTranses.IsAlive(tr)){
                wxString reason=_("Unknown Host");
	        if (TermIns) TermIns->OnScenarioEnd(reason==wxT("Succ"),reason);
	    }
	    return -1;
	}

	memset(&address,0,sizeof(address));
	address.sin_family = AF_INET;
	address.sin_addr.s_addr = inet_addr(inet_ntoa( *( struct in_addr*)( hostp -> h_addr_list[0])));

	wxString MsgDesc=_("Send Message");
	
	if (TermIns) {
	    Uid=TermIns->Uid;
	}
	else{
	   Uid=GetUidFromSipMsg(sip,STT_MSG_OUTGOING);
	   TermIns = wxGetApp().GetTermIns(Uid);
	}

	if ((TermIns) && (TermIns->RemotePort !=0)){
	    port=TermIns->RemotePort;
	}

	if (ForcePort!=0){
	    port=ForcePort;
	}
	address.sin_port = htons(port);

	int SendSock = UdpSocked;
	if (TermIns){
	    int SockIndex=TermIns->GetLocalPort()-ExSockStartPort;
	    if ((SockIndex>=0) &&(SockIndex<MAX_EX_SOCK_NUM)){
		SendSock = ExtUdpSocks[SockIndex];
	    }

	    TermIns->pCallInfo->LogString(wxString::Format(wxString(wxT("[%s %d]"))+_("%s [Total Len:%d]:\n%s"),STT_LStr(host), port, MsgDesc.c_str(),msgLen, STT_LStr(msgP)));
	}

	char sName[16]={0};
    	GetSipMsgName(sip,sName);

	STT_TRACE(Uid,TL_SIP_MESSAGE, wxString::Format(wxT("[%d,%s:%d,%s,%d]:\n%s"),STT_MSG_OUTGOING,STT_LStr(host), port,STT_LStr(sName),msgLen, STT_LStr(msgP)));

	/*STT_TRACE(Uid,TraceLevel, wxString::Format(wxString(wxT("[%s %d]"))+_("%s [Total Len:%d]:\n%s"),STT_LStr(host), port, MsgDesc.c_str(),msgLen, STT_LStr(msgP)));*/


	wxMutexLocker lock(s_mutexProtectingSocked);
	if(sendto(SendSock,msgP,msgLen,0,(struct sockaddr *)&address,sizeof(address)) < 0){
	  perror("sendto:");
	  STT_TRACE(Uid, TL_ERROR,_("networkMsgSend: sendto error"));
	  osip_free(msgP);
	  return -1;
	}

	wxGetApp().IncStatisticItem(STT_MSG_TOTAL_SENT);
	DoSendMsgStatistic(sip, msgP,msgLen);

	osip_free(msgP);
	return 0;

}

void OnTransTimeout(int type, osip_transaction_t *pott,osip_message_t *pomt)
{
    osip_message_t *pdst=NULL;
    if (pomt){
	osip_message_clone(pomt,&pdst);
    }
    else{
	osip_message_clone(pott->orig_request,&pdst);
    }
    int Uid=GetUidFromSipMsg(pdst,STT_MSG_OUTGOING);// atoi(to_t->url->username);
    DumpMsgKeyField(Uid,pdst);
    SttEvt *NewEvt=new SttEvt(type, pott,pdst,STTEVT_OSIP_TIMEOUT);
    wxGetApp().DisPatchEvt(Uid,NewEvt);
    //wxGetApp().DoLog(wxT("Some Transaction Timeout!!\n"));
}

int GetUidFromSipMsg(osip_message_t *pomt, int MsgType){
  int Uid=-1;
  char* uname=NULL;
  if ((MsgType==STT_MSG_INCOMMING) && (MSG_IS_REQUEST(pomt)) &&(0!=strcmp(pomt->sip_method,"REGISTER"))){
	osip_uri_t * uri=osip_message_get_uri(pomt);
	if (!uri) return -1;
      uname=uri->username;
  }
  else if (((MsgType==STT_MSG_INCOMMING) && (MSG_IS_REQUEST(pomt)))
      || ((!MSG_IS_REQUEST(pomt)) &&(MsgType==STT_MSG_OUTGOING))){
    osip_to_t *to_t = osip_message_get_to(pomt);
	if (!to_t) return -1;
    uname=to_t->url->username;
  }
  else{
    osip_from_t *to_t = osip_message_get_from(pomt);
	if (!to_t) return -1;
    uname=to_t->url->username;
  }
  if (!uname) return -1;
  wxString Uname(uname,*wxConvCurrent);
  Uname =Uname.Right(6);
  long v;
  Uname.ToLong(&v);
  Uid = v;
  return Uid;
}

//why we do this and not directly send the message from network to user
//is just use osip to remove all redundant message such as retransform message.
void OnRecvOsipMsg(int type, osip_transaction_t *pott,osip_message_t *pomt)
{

    int Uid=GetUidFromSipMsg(pomt,STT_MSG_INCOMMING);
    osip_message_t *pdst;
    osip_message_clone(pomt,&pdst);
    SttEvt *NewEvt=new SttEvt(type, pott,pdst);
    //printf("Trans:%p Message:0x%p\n",pott,pdst);
    wxGetApp().DisPatchEvt(Uid,NewEvt);

}

static void OsipKillTransaction(int type, osip_transaction_t *tr)
{
    wxGetApp().IncStatisticItem(STT_OSIP_TRANS_TOTAL_FREE);
    wxGetApp().AllTranses.RemoveTrans(tr,false);
}

void SetCallBacks(osip_t *osip){
  osip_set_cb_send_message(osip,SendOsipMsg);
  osip_set_message_callback(osip,OSIP_ICT_STATUS_1XX_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_ICT_STATUS_2XX_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_ICT_STATUS_3XX_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_ICT_STATUS_4XX_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_ICT_STATUS_5XX_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_ICT_STATUS_6XX_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_NICT_STATUS_1XX_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_NICT_STATUS_2XX_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_NICT_STATUS_3XX_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_NICT_STATUS_4XX_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_NICT_STATUS_5XX_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_NICT_STATUS_6XX_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_IST_INVITE_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_NIST_BYE_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_NIST_CANCEL_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_NIST_NOTIFY_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_NIST_SUBSCRIBE_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_NIST_OPTIONS_RECEIVED,OnRecvOsipMsg);

  osip_set_message_callback(osip,OSIP_NIST_INFO_RECEIVED,OnRecvOsipMsg);
  osip_set_message_callback(osip, OSIP_NIST_REGISTER_RECEIVED, &OnRecvOsipMsg);
  osip_set_message_callback(osip,OSIP_NIST_UNKNOWN_REQUEST_RECEIVED,OnRecvOsipMsg);

  osip_set_message_callback(osip, OSIP_ICT_STATUS_TIMEOUT, &OnTransTimeout);
  osip_set_message_callback(osip, OSIP_NICT_STATUS_TIMEOUT, &OnTransTimeout);

  osip_set_kill_transaction_callback (osip, OSIP_ICT_KILL_TRANSACTION, &OsipKillTransaction);
  osip_set_kill_transaction_callback (osip, OSIP_IST_KILL_TRANSACTION, &OsipKillTransaction);
  osip_set_kill_transaction_callback (osip, OSIP_NICT_KILL_TRANSACTION, &OsipKillTransaction);
  osip_set_kill_transaction_callback (osip, OSIP_NIST_KILL_TRANSACTION, &OsipKillTransaction);
}

bool Send100Try(osip_transaction_t *trans, osip_message_t* request)
{
	int status;
	osip_message_t *MsgPtr=NULL;
	if((status = osip_message_init(&MsgPtr)) != 0){
		STT_TRACE(-1,TL_ERROR,_("Can't init message!\n"));
		return false;
	}

	osip_message_set_method (MsgPtr, NULL);
	osip_message_set_uri (MsgPtr, NULL);
	int scode=100;
	osip_message_set_status_code(MsgPtr, scode);
	char *tmp = osip_strdup(osip_message_get_reason (scode));
	if (tmp == NULL){
	    osip_message_set_reason_phrase (MsgPtr, osip_strdup ("Unknown status code"));
	}
	else {
	    osip_message_set_reason_phrase (MsgPtr, tmp);
	}

	osip_to_clone (request->to, &(MsgPtr->to));
	osip_from_clone (request->from, &(MsgPtr->from));

	int pos = 0;
	while (!osip_list_eol (request->vias, pos))
	    {
		osip_via_t *via;
		osip_via_t *via2;

		via = (osip_via_t *) osip_list_get (request->vias, pos);
		int i = osip_via_clone (via, &via2);
		if (i != -0){
  		    STT_TRACE(-1,TL_ERROR,_("VIA Clone fail!\n"));
		    osip_message_free(MsgPtr);
		    return false;
		}
		osip_list_add (MsgPtr->vias, via2, -1);
		pos++;
	    }

	pos = 0;
	while (!osip_list_eol (request->record_routes, pos))
	    {
		osip_record_route_t *rr1;
		osip_record_route_t *rr2;

		rr1 = (osip_record_route_t *) osip_list_get (request->record_routes, pos);
		int i = osip_record_route_clone (rr1, &rr2);
		if (i != -0){
		    STT_TRACE(-1,TL_ERROR,_("Record Route Clone fail!\n"));
		    osip_message_free(MsgPtr);
		    return false;
		}
		osip_list_add (MsgPtr->record_routes, rr2, -1);
		pos++;
	    }

	osip_call_id_clone (request->call_id, &(MsgPtr->call_id));
	osip_cseq_clone (request->cseq, &(MsgPtr->cseq));

	osip_event_t       *sipeventPtr;
	if((sipeventPtr = osip_new_outgoing_sipmessage(MsgPtr)) == NULL){
	    STT_TRACE(-1,TL_ERROR,_("Can't allocate message!"));
	    osip_message_free(MsgPtr);
	    return false;
	}

	sipeventPtr->transactionid =  trans->transactionid;
	if((status = osip_message_force_update(MsgPtr)) != 0){
	    STT_TRACE(-1,TL_ERROR,_("Failed force update!"));
	    osip_message_free(MsgPtr);
	    return false;
	}

	if((status = osip_transaction_add_event(trans, sipeventPtr)) != 0){
	    STT_TRACE(-1,TL_ERROR,_("Can't add event!"));
	    osip_message_free(MsgPtr);
	    return false;
	}
	return true;

}


#define MAX_SIP_MSG_BUFFER 10000

//Because of Share bad data between Different thread, the design need to change,so backup it first.
void ProcessSipBuffer(char*msg,int n,sockaddr*cliaddr/*,int UdpSocked, sockaddr*cliaddr,int len*/){
    osip_event_t *sipevent;
    if (n>=MAX_SIP_MSG_BUFFER) n=MAX_SIP_MSG_BUFFER-1;
    if (n==0) return;
    msg[n]=0;
    wxGetApp().IncStatisticItem(STT_MSG_TOTAL_RECV);
    sipevent = osip_parse(msg,n);
    if((sipevent==NULL)||(sipevent->sip==NULL)){
      if (n==(MAX_SIP_MSG_BUFFER-1)){
	STT_TRACE(-1,TL_ERROR,wxString::Format(_("Sip Message Buffer Overflow:[%d]\n%s"),n,STT_LStr(msg)));
	DoRecvMsgStatistic(NULL, msg,n,_("OverFlowMsg"));
      }
      else{
	STT_TRACE(-1,TL_ERROR,wxString::Format(_("Could not parse SIP message (%d:)\n%s"),n,STT_LStr(msg)));
	DoRecvMsgStatistic(NULL, msg,n,_("FailParseMsg"));
      }
      osip_event_free(sipevent);
    }
    else{
	int status;
	int Uid=-1;
	Uid = GetUidFromSipMsg(sipevent->sip,STT_MSG_INCOMMING);

	char *callidstr=NULL;
	bool ValidMessage=false;
	if (!MSG_IS_NOTIFY(sipevent->sip)){
	  if (osip_call_id_to_str(sipevent->sip->call_id,&callidstr)==0){
	      if (wxGetApp().MatchCallId(Uid,callidstr,MSG_IS_REQUEST(sipevent->sip))){
	      ValidMessage=true;
	    }
	    osip_free(callidstr);
	  }
	}
	else{
	  ValidMessage=true;
	}

	if (ValidMessage){
	  TermControl* TermInst=wxGetApp().GetTermIns(Uid);
	  DoRecvMsgStatistic(sipevent->sip, msg,n,wxT(""));
	  if (TermInst){
	    TermInst->pCallInfo->LogString(wxString::Format(_("Recv Message [Total Len:%d]:\n%s"),n, STT_LStr(msg)));
	  }
	    
	 char sName[16]={0};
    GetSipMsgName(sipevent->sip,sName);

       wxString saddr(inet_ntoa(((struct sockaddr_in*)cliaddr)->sin_addr),wxConvUTF8);
	    saddr <<wxT(":")<< ntohs(((struct sockaddr_in*)cliaddr)->sin_port);
	    STT_TRACE(Uid,TL_MESSAGE,saddr);

    STT_TRACE(Uid,TL_SIP_MESSAGE,wxString::Format(wxT("[%d,%s,%s,%d]:\n%s"),STT_MSG_INCOMMING,saddr.c_str(),STT_LStr(sName),n,STT_LStr(msg)));

	    if((status = osip_find_transaction_and_add_event(wxGetApp().osip,sipevent)) != 0){
		if(MSG_IS_REQUEST(sipevent->sip)){
		    if (MSG_IS_ACK(sipevent->sip)){
			osip_message_t *pdst;
			osip_message_clone(sipevent->sip,&pdst);
			SttEvt *NewEvt=new SttEvt(0, (osip_transaction_t *)NULL,pdst);
			wxGetApp().DisPatchEvt(Uid,NewEvt);
			osip_event_free(sipevent);
		    }
		    else{
			TermControl *t=wxGetApp().GetTermIns(Uid);
			if (t){
			    osip_transaction_t *trans;
			    trans = osip_create_transaction(wxGetApp().osip,sipevent);
			    if (trans){
				osip_transaction_set_your_instance(trans,TermInst);
				wxGetApp().AllTranses.AddTrans(trans);
				wxGetApp().GetTermIns(Uid)->GetController().AddTransaction(trans);
				osip_transaction_add_event(trans,sipevent);

				if (MSG_IS_INVITE(sipevent->sip)){
				    //Auto Send 100 Try
				  if ((wxGetApp().frame)&&(wxGetApp().frame->gtMenu)&&(wxGetApp().frame->gtMenu->IsChecked(Minimal_GLOBAL_AUTO_100))){
				    Send100Try(trans,sipevent->sip);
				  }
				}
			    }
			    else{
				STT_TRACE(Uid,TL_ERROR,_("Create New Trans Fail!!"));
				osip_event_free(sipevent);
			    }
			}
			else{
			    osip_event_free(sipevent);
			}
		    }
		}
		else{
		    if ((wxGetApp().frame)&&(wxGetApp().frame->gtMenu)&&(!wxGetApp().frame->gtMenu->IsChecked(Minimal_GLOBAL_TRACE_SIP))){
			OnRecvOsipMsg(0, NULL, sipevent->sip);
		    }
		    else{
			STT_TRACE(Uid,TL_MESSAGE,_("Maybe Later Response Come!!"));
		    }
		    osip_event_free(sipevent);
		}
	    }
	}
	else{
	  DoRecvMsgStatistic(sipevent->sip, msg,n,_("Junk"));
	  STT_TRACE(-1,TL_MESSAGE,_("junk message recvd, throwed it up!"));
	  STT_TRACE(-1,TL_SIP_MESSAGE,wxString::Format(_("Recv Message [Total Len:%d]:\n%s"),n, STT_LStr(msg)));
	  osip_event_free(sipevent);
	}
    }
}


//This function should only use that thread safe function or data.
#if 0
void ProcessSipBuffer(char*msg,int n/*,int UdpSocked, sockaddr*cliaddr,int len*/){
    osip_event_t *sipevent;
    if (n>=MAX_SIP_MSG_BUFFER) n=MAX_SIP_MSG_BUFFER-1;
    if (n==0) return;
    msg[n]=0;
    wxGetApp().IncStatisticItem(STT_MSG_TOTAL_RECV);
    sipevent = osip_parse(msg,n);
    if((sipevent==NULL)||(sipevent->sip==NULL)){
      if (n==(MAX_SIP_MSG_BUFFER-1)){
	STT_TRACE(-1,TL_ERROR,wxString::Format(_("Sip Message Buffer Overflow:[%d]\n%s"),n,STT_LStr(msg)));
	DoRecvMsgStatistic(NULL, msg,n,_("OverFlowMsg"));
      }
      else{
	STT_TRACE(-1,TL_ERROR,wxString::Format(_("Could not parse SIP message (%d:)\n%s"),n,STT_LStr(msg)));
	DoRecvMsgStatistic(NULL, msg,n,_("FailParseMsg"));
      }
      osip_event_free(sipevent);
    }
    else{
	int status;
	DoRecvMsgStatistic(sipevent->sip, msg,n,wxT(""));
	if((status = osip_find_transaction_and_add_event(wxGetApp().osip,sipevent)) != 0){
		if(MSG_IS_REQUEST(sipevent->sip)){
		    if (MSG_IS_ACK(sipevent->sip)){
			osip_message_t *pdst;
			osip_message_clone(sipevent->sip,&pdst);
			SttEvt *NewEvt=new SttEvt(0, (osip_transaction_t *)NULL,pdst);
			wxGetApp().DisPatchEvt(GetUidFromSipMsg(pdst,STT_MSG_INCOMMING),NewEvt);
			osip_event_free(sipevent);
		    }
		    else{
		      osip_transaction_t *trans;
		      trans = osip_create_transaction(wxGetApp().osip,sipevent);
		      if (trans){
			wxGetApp().AllTranses.AddTrans(trans);
			osip_transaction_add_event(trans,sipevent);

			if (MSG_IS_INVITE(sipevent->sip)){
			  //Auto Send 100 Try
			  Send100Try(trans,sipevent->sip);
			}
		      }
		      else{
			STT_TRACE(-1,TL_ERROR,_("Create New Trans Fail!!"));
			osip_event_free(sipevent);
		      }
		    }
		}
		else{
		  //For Process those forking invite second response
		  if ((wxGetApp().frame)&&(wxGetApp().frame->gtMenu)&&(!wxGetApp().frame->gtMenu->IsChecked(Minimal_GLOBAL_THROW_JUNK_RESPONSE))){
		    OnRecvOsipMsg(0, NULL, sipevent->sip);
		  }
		  else{
		    //TODO : Maybe we need add some statistic here at least.
		    //STT_TRACE(-1,TL_SIP_MESSAGE,_("Maybe Later Response Come!!"));
		  }
		  osip_event_free(sipevent);
	    }
	}
    }
}
#endif


void *OsipRecvThread::Entry(){
    STT_TRACE(-1,TL_MESSAGE,_("Recv Thread Start Work!!"));
    TRACE_INITIALIZE(END_TRACE_LEVEL,NULL);
    int LastSockIndex=0;
    long timeoutlen=100 * (FD_SETSIZE-1);
    while (1){
	SOCKET RoundSocks[FD_SETSIZE-1]={0};
	int maxfd=UdpSocked;
	int len=0;
	for (int i=0;i<MAX_EX_SOCK_NUM;i++){
	    int cursock=(i+LastSockIndex) % MAX_EX_SOCK_NUM;
	    if (i>(FD_SETSIZE-1)){
		LastSockIndex = cursock;
		break;
	    }
	    RoundSocks[i]=ExtUdpSocks[cursock];
	    len=i;
	    if (ExtUdpSocks[cursock]>(SOCKET)maxfd){
		  maxfd=ExtUdpSocks[cursock];
	    }
	}


	fd_set readfds;
	struct timeval tv;
	int result;
	FD_ZERO(&readfds);
	FD_SET(UdpSocked,&readfds);

	tv.tv_sec = 0;
	tv.tv_usec = timeoutlen;

	{
		for (int i=0;i<=len;i++){
			FD_SET(RoundSocks[i],&readfds);
		}
	}

	result = select(maxfd+1,&readfds,NULL,NULL,&tv);
	if(result < 0){
	    break;
	}

	  if (wxGetApp().ApplicationExit) return NULL;

	  if (result>0){
	    if(FD_ISSET(UdpSocked,&readfds)){
		char msg[MAX_SIP_MSG_BUFFER];
		struct sockaddr cliaddr;
		int n;
		socklen_t len=sizeof(cliaddr);

		wxMutexLocker lock(s_mutexProtectingSocked);
		n = recvfrom(UdpSocked, msg, MAX_SIP_MSG_BUFFER, 0, (sockaddr*)&cliaddr, &len);
		if (n <0) {
		    int errfs=errno;
		    if ((errfs != EAGAIN) &&(errfs != 0)){
			STT_TRACE(-1,TL_ERROR,wxString::Format(_("recv() failed: error:%d\n"),errfs));
		    }
		}
		else{
		    wxGetApp().sipQueue.push_back(new SipRawMsg(msg,n,cliaddr));
		    //ProcessSipBuffer(msg,n/*,UdpSocked,(sockaddr*)&cliaddr,len*/);
		}
	    }

	    for (int i=0;i<=len;i++){
		if(FD_ISSET(RoundSocks[i],&readfds)){
		    char msg[MAX_SIP_MSG_BUFFER];
		    struct sockaddr cliaddr;
		    int n;
		    socklen_t len=sizeof(cliaddr);

		    wxMutexLocker lock(s_mutexProtectingSocked);
		    n = recvfrom(RoundSocks[i], msg, MAX_SIP_MSG_BUFFER, 0, (sockaddr*)&cliaddr, &len);
		    if (n <0) {
			int errfs=errno;
		    if ((errfs != EAGAIN) &&(errfs != 0)){
			STT_TRACE(-1,TL_ERROR,wxString::Format(_("recv() failed: error:%d\n"),errfs));
		    }
		    }
		    else{
			wxGetApp().sipQueue.push_back(new SipRawMsg(msg,n,cliaddr));
			    //ProcessSipBuffer(msg,n/*,ExtUdpSocks[i],(sockaddr*)&cliaddr,len*/);
		    }
		}
	    }
	  }
	  if (wxGetApp().ApplicationExit){//Does someone ask to delete me?
		  break;
	  }
	}

	return NULL;
}
